package com.yida.common.core.utils.mybatis;

import java.util.List;
import java.util.function.BiFunction;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class MybatisBatchUtils {
    
    /**
    * 每次处理1000条
    */
    private static final int BATCH_SIZE = 1000;
    
    //@Resource
    //@Autowired
    //@Resource
    //private SqlSessionFactory sqlSessionFactory;
    
    /**
     * 批量处理修改或者插入
     *
     * @param data     需要被处理的数据
     * @param mapperClass  Mybatis的Mapper类
     * @param function 自定义处理逻辑
     * @return int 影响的总行数
     */
//     public  <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function) {
//        
//         int i = 1;
//         SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
//         try {
//             U mapper = batchSqlSession.getMapper(mapperClass);
//             int size = data.size();
//             for (T element : data) {
//                 function.apply(element,mapper);
//                 if ((i % BATCH_SIZE == 0) || i == size) {
//                     batchSqlSession.flushStatements();
//                 }
//                 i++;
//             }
//             // 非事务环境下强制commit，事务情况下该commit相当于无效
//             batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
//         } catch (Exception e) {
//             batchSqlSession.rollback();
//             e.printStackTrace();
//         } finally {
//             batchSqlSession.close();
//         }
//         return i - 1;
//     }
    
    /**
     * 批量处理修改或者插入
     *
     * 使用案例：
     * @param data     需要被处理的数据
     * @param mapperClass  Mybatis的Mapper类
     * @param function 自定义处理逻辑
     * @return int 影响的总行数
     * batchUtils.batchUpdateOrInsert(数据集合, xxxxx.class, (item, mapper实例对象) -> mapper实例对象.insert方法(item));
     * int i = mbu.batchUpdateOrInsert(baseCommunityList, GwjBaseCommunityMapper.class, (GwjBaseCommunity,gwjBaseCommunityMapper)->gwjBaseCommunityMapper.insertGwjBaseCommunity(GwjBaseCommunity));
     */
     public  <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function,SqlSessionFactory sqlSessionFactory) {
    	 int i = 1;
         SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
         try {
             U mapper = batchSqlSession.getMapper(mapperClass);
             int size = data.size();
             for (T element : data) {
                 function.apply(element,mapper);
                 if ((i % BATCH_SIZE == 0) || i == size) {
                     batchSqlSession.flushStatements();
                 }
                 i++;
             }
             // 非事务环境下强制commit，事务情况下该commit相当于无效
             batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
         } catch (Exception e) {
             batchSqlSession.rollback();
             e.printStackTrace();
         } finally {
             batchSqlSession.close();
         }
         return i - 1;
     }
    
   /**
  	* 批量处理修改或者插入
  	*
  	* @param data     需要被处理的数据
  	* @param mapperClass  Mybatis的Mapper类
  	* @param function 自定义处理逻辑
  	* @return int 影响的总行数
  	*/
    public  <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function,Integer batchSize,SqlSessionFactory sqlSessionFactory){
    	return batchUpdateOrInsert(data,mapperClass,function,batchSize,true,sqlSessionFactory);
    }
     
    /**
    * 批量处理修改或者插入
    *
    * @param data     需要被处理的数据
    * @param mapperClass  Mybatis的Mapper类
    * @param function 自定义处理逻辑
    * @return int 影响的总行数
    */
    public  <T,U,R> int batchUpdateOrInsert(List<T> data, Class<U> mapperClass, BiFunction<T,U,R> function,Integer batchSize,boolean isSynchronizationActive,SqlSessionFactory sqlSessionFactory) {
        int i = 1;
        Integer batchSizeNum = 0;
	   	batchSizeNum = BATCH_SIZE;
	   	if(batchSize!=null) {
	   		batchSizeNum = batchSize;
	   	}
        SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            for (T element : data) {
                function.apply(element,mapper);
                if ((i % batchSizeNum == 0) || i == size) {
                    batchSqlSession.flushStatements();
                }
                i++;
            }
            //是否进行事务判断
            if(isSynchronizationActive) {
            	// 非事务环境下强制commit，事务情况下该commit相当于无效
                batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
            }else {
            	batchSqlSession.commit();
            }
        } catch (Exception e) {
            batchSqlSession.rollback();
            e.printStackTrace();
        } finally {
            batchSqlSession.close();
        }
        return i - 1;
    }
}
